// 文件名：list_event_queue.cpp
// 目的：基于 std::list 实现一个按优先级排队的事件队列。
// 功能：
//   - add(evt)：按优先级（priority）从高到低插入，保持队列有序；
//   - cancelByName(name)：按名称取消队列中所有匹配的事件；
//   - dispatch()：取出并处理队头事件；
//   - dump()：打印当前队列内容（调试）。
// 复杂度：
//   - add：O(n) 顺序查找插入点 + O(1) 链表插入；
//   - cancelByName：O(n) 遍历并按需擦除；
//   - dispatch：O(1) 取头部元素并弹出；
// 说明：
//   - 使用 std::list 可在中间插入/删除时保持迭代器稳定，适合队列频繁调整场景；
//   - 对相同优先级，保持先来先服务（稳定插入，新的会排到旧的后面）。

#include <list>
#include <iostream>
#include <string>

struct Event {
    std::string name;
    int priority; // 值越大优先级越高
};

class EventQueue {
public:
    // 按优先级从高到低插入（稳定：相同优先级新事件排在旧事件之后）
    void add(Event evt) {
        auto it = events_.begin();
        while (it != events_.end() && it->priority >= evt.priority) {
            ++it; // 跳过所有优先级 >= 新事件的元素
        }
        // 在第一个优先级更低的位置插入
        events_.insert(it, std::move(evt));
    }

    // 取消指定名称的所有事件
    void cancelByName(const std::string& name) {
        for (auto it = events_.begin(); it != events_.end();) {
            if (it->name == name) {
                it = events_.erase(it); // erase 返回下一个有效迭代器
            } else {
                ++it;
            }
        }
    }

    // 派发队头事件（若为空则提示）
    void dispatch() {
        if (!events_.empty()) {
            const auto evt = events_.front(); // 拷贝输出
            std::cout << "Dispatch: " << evt.name << " priority=" << evt.priority << '\n';
            events_.pop_front();
        } else {
            std::cout << "Queue empty\n";
        }
    }

    // 打印当前队列（从高优先到低优先）
    void dump() const {
        std::cout << "Pending:";
        for (const auto& e : events_) {
            std::cout << " [" << e.name << ":" << e.priority << "]";
        }
        std::cout << '\n';
    }

private:
    std::list<Event> events_; // 链表维护有序事件
};

int main() {
    EventQueue queue;
    queue.add({"render", 5});
    queue.add({"physics", 8});
    queue.add({"ai", 6});
    queue.dump();

    queue.cancelByName("render");
    queue.dump();

    queue.dispatch();
    queue.dispatch();
    queue.dispatch();
    return 0;
}